/*
 *  Copyright 2015-2016, RenGu Technology (BeiJing) Co., Ltd.
 *  All right reserved.
 *
 *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF RENGU TECHNOLOGY (BeiJing) CO., LTD.
 *
 *  THE CONTENTS OF THIS FILE MAY NOT BE DISCLOSED TO THIR PARTIES,
 *  COPIED OR DUPLICATED IN ANY FORM, IN WHOLE OR IN PART,
 *  WITHOUT THE PRIOR WRITTEN PERMISSION OF RENGU TECHNOLOGY (BeiJing) CO., LTD.
 *
 *  VirtAcctMultiMchntAdjustService
 *
 *  Edit History:
 *      lizhangtao Created on 2020年05月14日
 *
 */
package cc.rengu.igas.acct.core.service.trans;

import cc.rengu.igas.acct.common.dao.AcctDetailMapper;
import cc.rengu.igas.acct.common.dao.MapperCommon;
import cc.rengu.igas.acct.common.dao.impl.AcctDetailMapperImpl;
import cc.rengu.igas.acct.common.entity.AcctDetail;
import cc.rengu.igas.acct.common.enums.AcctRespCodeEnum;
import cc.rengu.igas.acct.common.enums.AcctTransStatusEnum;
import cc.rengu.igas.acct.core.service.realize.AcctOpt;
import cc.rengu.igas.acct.facade.bean.MchtAdjustDetail;
import cc.rengu.igas.acct.facade.request.VirtAcctMultiMchntAdjustRequest;
import cc.rengu.igas.acct.facade.response.VirtAcctMultiMchntAdjustResponse;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.List;

/**
 * 多账户记账实现
 *
 * @author lizhangtao
 * @version 1.0
 * @date 2020/5/14
 */
public class VirtAcctMultiMchntAdjustService extends RadpService {
    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @Override
    protected int bizProcess(String s, int i) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            VirtAcctMultiMchntAdjustRequest virtAcctMultiMchntAdjustRequest = new VirtAcctMultiMchntAdjustRequest();
            ConvertUtil.convertOutput(virtAcctMultiMchntAdjustRequest);
            rglog.info("virtAcctMultiMchntAdjustRequest = <{}>", JSONObject.toJSONString(virtAcctMultiMchntAdjustRequest));
            VirtAcctMultiMchntAdjustResponse virtAcctMultiMchntAdjustResponse = new VirtAcctMultiMchntAdjustResponse();
            virtAcctMultiMchntAdjustResponse.setHeader(virtAcctMultiMchntAdjustRequest.getHeader());
            virtAcctMultiMchntAdjustResponse.setMchtAdjustDetailList(virtAcctMultiMchntAdjustRequest.getMchtAdjustDetailList());
            BizResponse<VirtAcctMultiMchntAdjustResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(virtAcctMultiMchntAdjustResponse);
            String instId = virtAcctMultiMchntAdjustRequest.getHeader().getInstId();
            String frontSeqNum = virtAcctMultiMchntAdjustRequest.getHeader().getTraceNo();
            String debitCreditFlag = virtAcctMultiMchntAdjustRequest.getDebitCreditFlag();
            String acctAdjustSuffix = virtAcctMultiMchntAdjustRequest.getHeader().getTraceNo().length() >= 32 ? virtAcctMultiMchntAdjustRequest.getHeader().getTraceNo().substring(0, 32) : virtAcctMultiMchntAdjustRequest.getHeader().getTraceNo();

            List<MchtAdjustDetail> mchtAdjustDetailList = virtAcctMultiMchntAdjustRequest.getMchtAdjustDetailList();
            if (null == mchtAdjustDetailList || 0 == mchtAdjustDetailList.size() || 100 < mchtAdjustDetailList.size()) {
                rglog.error("多商户记账明细未上送或者明细数量超过100");
                throw new BizException(AcctRespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(),
                        AcctRespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
            //增加虚拟账户控制记账时，不允许同一笔流水号多次记账  先查询
            String virtAcctTraceNoCache = RedisUtil.getAndSet("ACCTADJUST" + acctAdjustSuffix,
                    virtAcctMultiMchntAdjustRequest.getHeader().getTraceNo());
            //认为已经记账
            if (!StringUtil.isNullorEmpty(virtAcctTraceNoCache)) {
                rglog.debug("从缓存中获取数据成功，认为已记账,key = <{}>", "ACCTADJUST" + acctAdjustSuffix);
                //查询返回数据，且同时记账成功，不需要二次记账
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
                throw new BizException(AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode(), AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
            }
            RedisUtil.onceExpire("ACCTADJUST" + acctAdjustSuffix, 60 * 60);
            //开启事物
            String dbPoolName = MapperCommon.getDbPoolName();
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            dbsUtil.dbsBeginTransaction();
            try {
                for (MchtAdjustDetail mchtAdjustDetail : mchtAdjustDetailList) {
                    //增加虚拟账户控制记账时，不允许同一笔流水号多次记账  先查询
                    AcctDetailMapper acctDetailMapper = new AcctDetailMapperImpl();
                    AcctDetail acctDetailSelect = acctDetailMapper.selectAcctDetailByFromSeqNumCustomerIdAndUserId(mchtAdjustDetail.getUserId(), mchtAdjustDetail.getUserType(),
                            mchtAdjustDetail.getAcctNo(), mchtAdjustDetail.getCustomerId(),
                            acctAdjustSuffix,
                            virtAcctMultiMchntAdjustRequest.getHeader().getInstId());
                    if (null != acctDetailSelect && "00".equals(acctDetailSelect.getAcctStatus())) {
                        //查询返回数据，且同时记账成功，不需要二次记账
                        rglog.error("查询返回数据，且同时记账成功，不需要二次记账;  acctDetailSelect = <{}>", JSON.toJSONString(mchtAdjustDetail));
                        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespCode());
                        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, AcctRespCodeEnum.STATUS_NOT_ALLOW_ERROR.getRespDesc());
                        continue;
                    }
                    //调用普通借贷记 无事物，不提交、不回滚
                    AcctDetail acctDetail = new AcctOpt().normal(virtAcctMultiMchntAdjustRequest.getHeader().getTransDate(),
                            virtAcctMultiMchntAdjustRequest.getHeader().getTransTime(),
                            virtAcctMultiMchntAdjustRequest.getHeader().getTxnNum(),
                            virtAcctMultiMchntAdjustRequest.getHeader().getSrcSysId(), instId, frontSeqNum,
                            mchtAdjustDetail.getTransAmt(), debitCreditFlag,
                            mchtAdjustDetail.getAcctNo(), mchtAdjustDetail.getCustomerId(),
                            mchtAdjustDetail.getUserType(), mchtAdjustDetail.getUserId(),
                            mchtAdjustDetail.getSummary(), dbsUtil, rglog, mchtAdjustDetailList.size());

                    BeanUtil.beanCopy(acctDetail, mchtAdjustDetail);
                }
            } catch (BizException e) {
                dbsUtil.dbsEndTransaction(false);
                throw e;
            } catch (Exception e) {
                dbsUtil.dbsEndTransaction(false);
                throw new BizException(AcctRespCodeEnum.MULTI_MCHNT_ADJUST.getRespCode(),
                        AcctRespCodeEnum.MULTI_MCHNT_ADJUST.getRespDesc());
            }
            dbsUtil.dbsEndTransaction(true);
            virtAcctMultiMchntAdjustResponse.setRespCode(OltpRpcdEnum.TRANS_SUCCESS.getRespCode());
            virtAcctMultiMchntAdjustResponse.setRespDesc(OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            virtAcctMultiMchntAdjustResponse.setTransStatus(AcctTransStatusEnum.SUCC.getStatus());
            bizResponse.setRspSysId(ChannelEnum.ACCT.getChannelType());
            bizResponse.setRespCode(OltpRpcdEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            bizResponse.setTransStatus(TransStatusEnum.TRANS_SUCC);

            ConvertUtil.convertInput(bizResponse.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE,
                        OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC,
                        OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }
        return 0;
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }
}
